/**
 * Copyright (C) 2011 Andrew C. Love (DNC) <dnc.app.sup@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dnc.cloak.framework.pool;

import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;

public class PoolMgr {

	private static final Logger logger = Logger.getLogger(PoolMgr.class.getName());
	private static Map<String, Pool<?>> pools = Collections.synchronizedMap(new TreeMap<String, Pool<?>>());
	
	public static synchronized Class<?> requestClass (String className) throws PoolException {
		
		try {
			return Class.forName(className);
			
		} 
		catch (ClassNotFoundException ex) {			
			throw new PoolException(ex);			
		}
		
	}
		
	
	@SuppressWarnings("unchecked")
	public static synchronized <T> T request (String className) throws PoolException {
		
		try {
			Pool<T> pool = getPool(className, true);
			
			if (pools.containsKey(className)){			
				pool = (Pool<T>)pools.get(className);			
			}
			else {			
				pool = new Pool<T>(className);
				pools.put(className,pool);
			}
			
			return pool.request();
			
		} 
		catch (PoolException ex) {
			logger.error(ex);			
			throw ex;
		}		
		
	}
	
	public static synchronized <T> void release (T pooledObject ) throws PoolException {
		
		String className = pooledObject.getClass().getName();		
		release(className,pooledObject);
		
	} 

	public static synchronized <T> void release (String className, T pooledObject ) throws PoolException {
		
		Pool<T> pool = getPool(className, true);
		
		if (pools.containsKey(className)){			
			pool.release(pooledObject);
		}
		
	} 
	
	public static int getPoolSize(String className) throws PoolException {
		return getPool(className, true).getPoolSize();
	}
	
	public static int getPoolCount(String className) throws PoolException {
		return getPool(className, true).getPoolCount();
	}
	
	@SuppressWarnings("unchecked")
	public static synchronized <T> Pool<T> getPool(String className, boolean create) throws PoolException {
		Pool<T> pool = null;
		
		if (pools.containsKey(className)){			
			pool = (Pool<T>)pools.get(className);			
		}
		else {
			if (create) {
				pool = new Pool<T>(className);
				pools.put(className,pool);				
			}
		}
		
		return pool;
		
	}

}
